package com.arashivision.onecamerademo;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.arashivision.arcompose.GyroType;
import com.arashivision.extradata.ARObject;
import com.arashivision.extradata.protobuf.ExtraMetadata;
import com.arashivision.onecamera.AudioSource;
import com.arashivision.onecamera.Error;
import com.arashivision.onecamera.OneDriverInfo;
import com.arashivision.onecamera.OneLatestIDR;
import com.arashivision.onecamera.Options;
import com.arashivision.onecamera.PhotoOptions;
import com.arashivision.onecamera.RecordType;
import com.arashivision.onecamera.StartCaptureWithoutStorage;
import com.arashivision.onecamera.StartStreamingParam;
import com.arashivision.onecamera.cameranotification.BTPeripheral;
import com.arashivision.onecamera.camerarequest.AudioParam;
import com.arashivision.onecamera.camerarequest.ConnectToBTPeripheral;
import com.arashivision.onecamera.camerarequest.DeleteFiles;
import com.arashivision.onecamera.camerarequest.GetFileExtra;
import com.arashivision.onecamera.camerarequest.GetFileList;
import com.arashivision.onecamera.camerarequest.GetTimelapseOptions;
import com.arashivision.onecamera.camerarequest.GyroOptionIndexRange;
import com.arashivision.onecamera.camerarequest.GyroOptionTimeRange;
import com.arashivision.onecamera.camerarequest.ScanBTPeripheral;
import com.arashivision.onecamera.camerarequest.SetFileExtra;
import com.arashivision.onecamera.camerarequest.SetTimelapseOptions;
import com.arashivision.onecamera.camerarequest.StartTimelapse;
import com.arashivision.onecamera.camerarequest.StopTimelapse;
import com.arashivision.onecamera.camerarequest.TakePicture;
import com.arashivision.onecamera.camerarequest.TestSDCardSpeed;
import com.arashivision.onecamera.camerarequest.TimelapseOptionsInfo;
import com.arashivision.onecamera.camerarequest.VideoParam;
import com.arashivision.onecamera.camerarequest.WifiInfo;
import com.arashivision.onecamera.cameraresponse.GetOptionsResp;
import com.arashivision.onecamera.render.RenderMethod;
import com.arashivision.onecamera.render.RenderMode;
import com.arashivision.onestreamtarget.OneStreamTarget;
import com.clj.blesample.AnyScanActivity;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_1920_960P30;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_2048_512P120;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_2560_1280P30;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_2560_1280P60;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_2880_2880P30;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_3328_832P60;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_3840_1920P30;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_3840_1920P60;
import static com.arashivision.onecamera.OneDriverInfo.Options.VideoResolution.RES_3840_960P100;


public class PlaneActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "OnePlaneActivity";
    private static final boolean DEVELOPER_MODE = true;
    private static final int MY_PERMISSIONS_REQUEST_ACCESS_EXTERNAL_STORAGE = 1;
    private CameraService mCameraService;
    private SurfaceView mSurfaceView;
    private SurfaceView mSurfaceView2;
    private boolean mOpen;
    private Button mOpenButton;
    private Button mPhotoButton;
    private Button mRecordButton;
    private Button mGetInfoButton;
    private Button mUploadLogButton;
    private Button mLivePushButton;
    private Button mScanBT;
    private Button mConnectBT;
    private Button mDeleteFileList;
    private Button mGetFileList;
    private Button mGetOption;
    private Button mBleButton;
    private Button mGetPhotoOption;
    private Button mEraseSdcard;
    private Button mTestSdcard;
    private Button mSetFileExtra;
    private Button mGetFileExtra;
    private TextView mInfoView;
//    private TextView mVersionTextView;
    private TextView mLiveFpsTextView;
    private Surface mSurface;
    private Surface mSurface2;
    private ImageView mPhotoView;
    private SeekBar mIsoSeekBar;
    private SeekBar mEVSeekBar;
    private SeekBar mShutterSeekBar;
    private SeekBar mWhiteBalanceSeekBar;
    private Spinner mSpinner;
    private Spinner mXUSpinner;
    private Spinner mIndexSpiner;
    private EditText mIsoValueEdit;
    private EditText mEVValueEdit;
    private EditText mShutterValueEdit;
    private EditText mWhiteBalanceValueEdit;
//    private EditText mBitrateValueEdit;
    private EditText mLiveUrlEdit;
    private EditText mLiveFpsEdit;
    private EditText mLiveBitrateEdit;
    private EditText mLiveWidthEdit;
    private EditText mLiveHeightEdit;
    private EditText mQFactorEdit;
    private Switch mExposeModeSwitch;
    private Switch mStreamNum;
    private Spinner mTarget;
    private String mFwReleaseName;

    private int mVideoWidth = 3840;
    private int mVideoHeight = 1920;
    private int fps = 30;
    private int bitRate = 0;
    private boolean mPanoMode = false;
    private int mISOProgress;
    private boolean bEnableGyro = false;
    private int mIndexSpinnerPosition = 0;
    private boolean mRunnning;
    private int funcMode = OneDriverInfo.PhotoOptionsConstants.FunctionMode.FUNCMODE_NORMAL;

    private enum RecordState { Idle, Recording, Stopping }
    private RecordState mRecordState = RecordState.Idle;
    private ConnectToBTPeripheral mConectObj;

    public static boolean mDualStream = true;
    private GyroType mGyroType = GyroType.One2;
    public static boolean mStreamTarget = false;
    public static boolean mDualStreamTarget = false;
    public static boolean mStreamTargetShadowTexture = false;
    public static boolean mGLTarget = false;


    private int mPreviewNum = 1;

    public static final int STREAMTARGET_TEXTURE = 0;
    public static final int DUAL_GLTARGET = 1;
    public static final int DUAL_SURFACE = 2;
    public static final int STREAMTARGET_SURFACE = 3;


    public static final int DUAL_STREAMTARGET = 4;

    public static String mOffset;

    private Object syncCmd = new Object();

    private Object mResult = new Object();
    private int mCmdWhat;

    private int mTimelapseMode;

    public static final int CMD_TO = 10000;

    private static int clampValue(int value, int originMin, int originMax, int dstMin, int dstMax) {
        return (value - originMin) * (dstMax - dstMin) / (originMax - originMin) + dstMin;
    }

    private String getAppVersion() {
        PackageManager manager = getPackageManager();
        PackageInfo info = null;
        try {
            info = manager.getPackageInfo(getPackageName(), 0);
        } catch(PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return "Unknown version";
        }
        return info.versionName;
    }

    private String getFwVersionInfo() {
        mFwReleaseName = null;
        return "unknown-unknown";
    }

    private void testCurrentDateTime()
    {
        Calendar now = Calendar.getInstance();
        Log.d(TAG,"年：" + now.get(Calendar.YEAR));
        Log.d(TAG,"月：" + (now.get(Calendar.MONTH) + 1));
        Log.d(TAG,"日：" + now.get(Calendar.DAY_OF_MONTH));
        Log.d(TAG,"时：" + now.get(Calendar.HOUR_OF_DAY));
        Log.d(TAG,"分：" + now.get(Calendar.MINUTE));
        Log.d(TAG,"秒：" + now.get(Calendar.SECOND));
        //使用Date
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Log.d(TAG,"当前时间：" + sdf.format(d));
    }

    private String transForDate(long ms) throws ParseException
    {
        long msl= ms;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String res = null;
        if(ms >= 0){
            Long time= new Long(msl);
            res = sdf.format(time);
            Log.d(TAG,"ms is " + ms + " res is " + res);
        }
        return res;
    }


    private void switchDualFishMode()
    {
        String offset = readCameraOffset();
        if(offset == null)
            offset = "";
        Toast.makeText(PlaneActivity.this, "切换到全景模式, offset: " + offset, Toast.LENGTH_LONG).show();
        mCameraService.updatePanoOffset(offset);
        mCameraService.switchRenderMode(RenderMode.withGlRenderer(RenderMethod.DualFishEyeStitchingPlanar));
        mPanoMode = true;
    }

    private void startPreviewActivity()
    {
        Intent intent = new Intent(PlaneActivity.this, PreviewActivity.class);
        startActivity(intent);
    }

    private Object startWait(long id,int cmd)
    {
        Log.d(TAG,"id " + id + " cmd " + cmd);
        synchronized (syncCmd)
        {
            try
            {
                mCmdWhat = -1;
                mResult = null;
                syncCmd.wait(10000);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        Object result = null;
        if(mResult != null && mCmdWhat == cmd)
        {
            GetOptionsResp resp = (GetOptionsResp)mResult;
            if(id == resp.requestID)
            {
                result = resp.result;
            }
            else
            {
                Log.e(TAG,"error testGetOptions mismatch (" +
                        id + "," + resp.requestID +") cmd " + cmd);
            }
        }
        else
        {
            Log.e(TAG,"error startWait  " +
                    id + " cmd " + cmd + " mCmdWhat " + mCmdWhat);
            if(mResult == null)
            {
                Log.e(TAG," mResult null");
            }
        }

        return result;
    }

    private Options testGetOptions(List<String> list)
    {
        long id = mCameraService.getOptionsAsync(list);
        return (Options)startWait(id,OneDriverInfo.Response.InfoType.GET_OPTIONS);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        if (DEVELOPER_MODE) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()   // or .detectAll() for all detectable problems
                    .penaltyLog()
                    .build());
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                    .detectLeakedSqlLiteObjects()
                    .detectLeakedClosableObjects()
                    .penaltyLog()
                    .penaltyDeath()
                    .build());
        }

        super.onCreate(savedInstanceState);

        Log.d(TAG," keep sreen on mDualStream " + mDualStream);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

//        if(mDualStream)
//        {
//            mPreviewNum = 1;
//        }
//        else
//        {
//            mPreviewNum = 0;
//        }
        setContentView(R.layout.activity_plane2);

        //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);

        EventBus.getDefault().register(this);
        Log.d(TAG,"onCreate");
        mCameraService = CameraService.instance(this.getApplicationContext());

        mCameraService.setInfoNotify(new CameraService.InfoNotify()
        {
            @Override
            public void infoNotify(int what,int error,Object obj)
            {
                Log.d(TAG,"infoNotify " + what + " " + error);
                if(error == 0)
                {
                    synchronized (syncCmd)
                    {
                        mCmdWhat = what;
                        if(obj == null)
                        {
                            Log.e(TAG,"obj null");
                        }
                        else
                        {
                            Log.d(TAG,"obj " + obj);
                        }

                        mResult = obj;

                        syncCmd.notifyAll();
                    }
                }
                Log.d(TAG,"infoNotify over");
            }
        });
        Log.d(TAG,"onCreate suc");
        mScanBT = (Button) findViewById(R.id.ap_calibrate_gyro);
        mScanBT.setOnClickListener(this);
        mScanBT.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                scanBT(OneDriverInfo.Request.BTPeripheralType.BTPERIPHERALTYPE_ALL);
                return true;
            }
        });

        mConnectBT = (Button) findViewById(R.id.ap_get_gyro);
        mConnectBT.setOnClickListener(this);
        mDeleteFileList = (Button) findViewById(R.id.ap_delete_file);
        mDeleteFileList.setOnClickListener(this);

        mGetFileList = (Button) findViewById(R.id.ap_get_file);
        mGetFileList.setOnClickListener(this);

        mGetOption = (Button) findViewById(R.id.get_option);
        mGetOption.setOnClickListener(this);

        mBleButton = (Button) findViewById(R.id.start_ble);
        mBleButton.setOnClickListener(this);

        mGetPhotoOption = (Button) findViewById(R.id.get_photo_option);
        mGetPhotoOption.setOnClickListener(this);

        mEraseSdcard = (Button) findViewById(R.id.erase_sdcard);
        mEraseSdcard.setOnClickListener(this);

        mTestSdcard = (Button) findViewById(R.id.test_card);
        mTestSdcard.setOnClickListener(this);


        mSetFileExtra = (Button) findViewById(R.id.ap_set_file_extra);
        mSetFileExtra.setOnClickListener(this);
        mGetFileExtra= (Button) findViewById(R.id.ap_get_file_extra);
        mGetFileExtra.setOnClickListener(this);

        mOpenButton = (Button) findViewById(R.id.ap_bt_open);
        mOpenButton.setOnClickListener(this);
        mPhotoButton = (Button) findViewById(R.id.ap_bt_takephoto);
        mPhotoButton.setOnClickListener(this);
        mRecordButton = (Button) findViewById(R.id.ap_bt_record);
        mRecordButton.setOnClickListener(this);

        mOpenButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                Log.d(TAG,"onLongClick mOpen " + mOpen);
                if(!mOpen)
                {
                    openWifi();
                }
                return true;
            }
        });
        mRecordButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(mRecordState == RecordState.Idle)
                {
                    Log.d(TAG,"record without card");
                    startRecord(false, false);
                }
                return true;
            }
        });

        mPhotoButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(mRecordState == RecordState.Idle)
                {
                    Log.d(TAG,"picture without card");
                    String filename = new File(Environment.getExternalStorageDirectory(), "one_demo/photo_" +
                            new SimpleDateFormat("MM_dd_HH_mm_ss_SSS", Locale.getDefault()).format(new Date()) + ".jpg").getAbsolutePath();

                    testCaptureStillImageWithouStorage(filename,false);
                }
                return true;
            }
        });

        mGetPhotoOption.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                testSetPhotoOption();
                return true;
            }
        });

        mGetOption.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                testSetOption();
                return true;
            }
        });

        mLivePushButton = (Button) findViewById(R.id.ap_bt_live_push);
        mLivePushButton.setOnClickListener(this);
        mPhotoView = (ImageView) findViewById(R.id.ap_photoview);
        mGetInfoButton = (Button) findViewById(R.id.ap_bt_getinfo);
        mIndexSpiner = (Spinner) findViewById(R.id.ap_spinner_index);
        mInfoView = (TextView) findViewById(R.id.ap_tv_info);
        mGetInfoButton.setOnClickListener(this);
        mGetInfoButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!mOpen) {
                    Log.i(TAG, "camera not running");
                    return;
                }
                String info = null;
                String name = "unknown";
                List<String> mList = new ArrayList<String>();
                Options mOption;
                switch(mIndexSpinnerPosition)
                {
                    case 0:
                        name = OneDriverInfo.Options.MEDIA_OFFSET;
                        mList.add(name);
                        mOption = testGetOptions(mList);
                        if(mOption != null)
                        {
                            info = mOption.getMediaOffset();
                        }
                        break;
                    case 1:
                        name = OneDriverInfo.Options.ONE_UUID;
                        mList.add(name);
                        mOption = testGetOptions(mList);
                        if(mOption != null)
                            info = mOption.getUUID();
                        break;
                    case 2:
                        name = OneDriverInfo.Options.SERIAL_NUMBER;
                        mList.add(name);
                        mOption = testGetOptions(mList);
                        if(mOption != null)
                            info = mOption.getSN();
                        break;
                    case 3:
                        name = OneDriverInfo.Options.ACTIVATE_TIME;
                        mList.add(name);
                        mOption = testGetOptions(mList);
                        if(mOption != null)
                        {
                            try
                            {
                                info = transForDate(mOption.getActiveTime());
                            } catch (ParseException e)
                            {
                                e.printStackTrace();
                            }
                        }

                        break;
                    default:
                        break;
                }

                if(info != null) {
                    Log.i(TAG, "read camera " + name + ": " + info);
                    mInfoView.setText(info);
                } else {
                    mInfoView.setText(name + " not stored in camera ");
                }
            }
        });
        mGetInfoButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(!mOpen) {
                    Log.i(TAG, "camera not running");
                    return true;
                }
                String info = mInfoView.getText().toString();
                String name = "unknown";
                Options mOption = new Options();

                switch(mIndexSpinnerPosition)
                {
                    case 0:
                        name = OneDriverInfo.Options.MEDIA_OFFSET;
                        mOption.setMediaOffset(info);
                        mCameraService.setOptionsAsync(mOption);
                        break;
                    case 1:
                        name = OneDriverInfo.Options.ONE_UUID;
                        info = "uuid not allowed";
                        break;
                    case 2:
                        name = OneDriverInfo.Options.SERIAL_NUMBER;
                        mOption.setSN(info);
                        mCameraService.setOptionsAsync(mOption);
                        break;
                    case 3:
                        name = OneDriverInfo.Options.ACTIVATE_TIME;

                        long active_ms = Calendar.getInstance().getTimeInMillis();

                        if(info.equals("0"))
                        {
                            active_ms = 0;
                        }

                        Log.d(TAG,"info " + info + " active_ms " + active_ms);
                        mOption.setActiveTime(active_ms);
                        mCameraService.setOptionsAsync(mOption);

                        Log.d(TAG,"write active time " +
                                active_ms + " now is " +
                                new Date());
                        try
                        {
                            Log.d(TAG,"datetime " + transForDate(active_ms) );

                        } catch (ParseException e)
                        {
                            Log.e(TAG,"parse exception");
                            e.printStackTrace();
                        }
                        break;
                    default:
                        throw new IllegalStateException("mIndexSpinnerPosition " + mIndexSpinnerPosition);
                }
                Toast.makeText(PlaneActivity.this, "写入" + name + "成功 " + info, Toast.LENGTH_LONG).show();
                return true;
            }
        });
        mIndexSpiner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                int oldSpinnerPosition = mIndexSpinnerPosition;
                mIndexSpinnerPosition = position;
                if(oldSpinnerPosition != mIndexSpinnerPosition)
                    mInfoView.setText("");
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

//        mBitrateValueEdit = (EditText) findViewById(R.id.ap_et_bitrate);

        mIsoValueEdit = (EditText) findViewById(R.id.ap_et_iso_value);
        mEVValueEdit = (EditText) findViewById(R.id.ap_et_ev_value);
        mShutterValueEdit = (EditText) findViewById(R.id.ap_et_shutter_value);
        mWhiteBalanceValueEdit = (EditText) findViewById(R.id.ap_et_whitebalance_value);

//        mEVValueEdit.setHint(EV_MIN + "~" + EV_MAX);
//        mShutterValueEdit.setHint(SHUTTER_MIN + "~" + SHUTTER_MAX);
//        mWhiteBalanceValueEdit.setHint(WB_MIN + "~" + WB_MAX);

        mIsoValueEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if(actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
                    if(mIsoValueEdit.getText() != null)
                    {
                        int isoValue = (Integer.parseInt(mIsoValueEdit.getText().toString()) - 100);
                        return true;
                    }
                }
                return false;
            }
        });
        mEVValueEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if(actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
                    int evValue = Integer.parseInt(mEVValueEdit.getText().toString());
                    Log.i(TAG, "ev edit value: " + evValue);
                    return true;
                }
                return false;
            }
        });
        mShutterValueEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if(actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
                    return true;
                }
                return false;
            }
        });
        mWhiteBalanceValueEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if(actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
                    int wbValue = Integer.parseInt(mWhiteBalanceValueEdit.getText().toString());
                    Log.i(TAG, "iso edit value: " + wbValue);
                    return true;
                }
                return false;
            }
        });
        mLiveBitrateEdit = (EditText)findViewById(R.id.bitrate_edit);
        mLiveFpsEdit = (EditText)findViewById(R.id.fps_edit);
        mLiveUrlEdit = (EditText)findViewById(R.id.live_addr_edit);
        mLiveWidthEdit = (EditText)findViewById(R.id.width_edit);
        mLiveHeightEdit = (EditText)findViewById(R.id.height_edit);

        mQFactorEdit = (EditText)findViewById(R.id.ap_et_qfacotor);

//        mVersionTextView = ((TextView) findViewById(R.id.ap_tv_versioninfo));
//        setVersionInfo();
//        mVersionTextView.setOnLongClickListener(new View.OnLongClickListener() {
//            @Override
//            public boolean onLongClick(View v) {
//                return true;
//            }
//        });
        mLiveFpsTextView = (TextView)findViewById(R.id.live_fps_view);

        mSurfaceView = (SurfaceView) findViewById(R.id.ap_surfaceView);
        mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                mSurface = holder.getSurface();
                Log.d(TAG,"surfaceCreated after set format mSurface " + mSurface);
                setSurface();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                Log.d(TAG,"surfaceChanged width " + width + " height " + height);
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                Log.d(TAG,"surfaceDestroyed mCameraService.getSurface() " +
                        mCameraService.getSurface() + " mSurface " + mSurface);
                if(mCameraService.getSurface() == mSurface) {
                    Log.d(TAG,"surfaceDestroyed");
                    mCameraService.setSurface(null,null);
                }
                else
                {
                    android.util.Log.e(TAG,"surfaceDestroyed mismtach");
                }
                mSurface = null;
            }
        });
        mSurfaceView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!mDualStream)
                {
                    if(mPanoMode) {
                        Toast.makeText(PlaneActivity.this, "切换到原始视频直接渲染模式", Toast.LENGTH_LONG).show();
                        mCameraService.switchRenderMode(RenderMode.directDecoding());
                        mPanoMode = false;
                    } else {
                        switchDualFishMode();
                    }
                }
            }
        });
        mSurfaceView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                startPreviewActivity();
                return true;
            }
        });

        mSurfaceView2 = (SurfaceView) findViewById(R.id.ap_surfaceView2);
            mSurfaceView2.getHolder().addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    mSurface2 = holder.getSurface();
                    Log.d(TAG,"surfaceCreated2 mSurface " + mSurface);
                        setSurface();
                }
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                    Log.d(TAG,"surfaceChanged2 width " + width + " height " + height);
                }
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    Log.d(TAG,"surfaceDestroyed2 mCameraService.getSurface2() " +
                            mCameraService.getSurface2() + " mSurface2 " + mSurface2);
                    if(mCameraService.getSurface2() == mSurface2)
                    {
                        mCameraService.setSurface(null,null);
                    }
                    else
                    {
                        android.util.Log.e(TAG,"surfaceDestroyed2 mismtach");
                    }
                    mSurface2 = null;
                }
            });
            mSurfaceView2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(!mDualStream)
                    {
                        if(mPanoMode) {
                            Toast.makeText(PlaneActivity.this, "切换到原始视频直接渲染模式", Toast.LENGTH_LONG).show();
                            mCameraService.switchRenderMode(RenderMode.directDecoding());
                            mPanoMode = false;
                        } else {
                            switchDualFishMode();
                        }
                    }
                }
            });
            mSurfaceView2.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    Intent intent = new Intent(PlaneActivity.this, PreviewActivity.class);
                    startActivity(intent);
                    return true;
                }
            });

        mIsoSeekBar = (SeekBar) findViewById(R.id.ap_sb_iso);
        mEVSeekBar = (SeekBar) findViewById(R.id.ap_sb_ev);
        mShutterSeekBar = (SeekBar) findViewById(R.id.ap_sb_shutter);
        mWhiteBalanceSeekBar = (SeekBar) findViewById(R.id.ap_sb_whitebalance);

        mIsoSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if(!fromUser)
                    return;
                Log.i(TAG, "iso seek bar progress: " + progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
        mEVSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if(!fromUser)
                    return;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
        mShutterSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if(!fromUser)
                    return;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
        mWhiteBalanceSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if(!fromUser)
                    return;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        mSpinner = (Spinner) findViewById(R.id.spinner);
        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mDualStream = false;
                Log.d(TAG,"position " + position);
                switch(position)
                {
                    case RES_3840_1920P30:
//                        if(mDualStream)
//                        {
//                            mVideoWidth = 3840;
//                            mVideoHeight = 1920;
//                            fps = 30;
//                            bitRate = 45;
//                        }
//                        else
                        {
                            mVideoWidth = 3840;
                            mVideoHeight = 1920;
                            fps = 30;
//                            bitRate = 40;
                        }
                        break;
                    case RES_2560_1280P30:
                        mVideoWidth = 2560;
                        mVideoHeight = 1280;
                        fps = 30;
                        break;
                    case RES_1920_960P30:
                        mVideoWidth = 1920;
                        mVideoHeight = 960;
                        fps = 30;
                        break;
                    case RES_2560_1280P60:
                        mVideoWidth = 2560;
                        mVideoHeight = 1280;
                        fps = 60;
                        break;
                    case RES_2048_512P120:
                        mVideoWidth = 2048;
                        mVideoHeight = 512;
                        fps = 120;
                        break;
                    case RES_3328_832P60:
                        mVideoWidth = 3328;
                        mVideoHeight = 832;
                        fps = 60;
                        break;
                    default:
                        Log.d(TAG," position " + position + " select " + (position + (RES_2880_2880P30 - RES_3328_832P60 - 1)));
                        switch(position + (RES_2880_2880P30 - RES_3328_832P60 - 1))
                        {
                            case RES_2880_2880P30:
                                mDualStream = true;
                                mVideoWidth = 5760;
                                mVideoHeight = 2880;
                                fps = 30;
//                                bitRate = 45;
                                break;
                            case RES_3840_1920P60:
                                mVideoWidth = 3840;
                                mVideoHeight = 1920;
                                fps = 60;
//                                bitRate = 0;
                                break;
                            case RES_3840_960P100:
                                mVideoWidth = 3840;
                                mVideoHeight = 960;
                                fps = 100;
//                                bitRate = 0;
                                break;
                            default:
                                Log.e(TAG, "unknown position: " + position);
                                break;
                        }
                        break;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        mXUSpinner = (Spinner) findViewById(R.id.ap_spinner_xu);
        mXUSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if(position == 0) {
                    // iso
                    setViewVisible(ViewItem.ISO);
                } else if(position == 1) {
                    // ev
                    setViewVisible(ViewItem.EV);
                } else if(position == 2) {
                    // shutter
                    setViewVisible(ViewItem.SHUTTER);
                } else if(position == 3) {
                    // white balance
                    setViewVisible(ViewItem.WB);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        mExposeModeSwitch = (Switch) findViewById(R.id.ap_sw_exposemode);
        mExposeModeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            }
        });

        mStreamNum = (Switch) findViewById(R.id.ap_stream_num);
        mStreamNum.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            }
        });

        mTarget = (Spinner) findViewById(R.id.spinner_target);
        mTarget.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
        {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
            {
                Log.d(TAG,"target position " + position);
                switch (position)
                {
                    case STREAMTARGET_TEXTURE:
                        mStreamTarget = true;
                        mDualStreamTarget = false;
                        mStreamTargetShadowTexture = true;
                        break;
                    case DUAL_GLTARGET:
                        mStreamTarget = false;
                        mGLTarget = true;
                        mDualStreamTarget = false;
                        break;
                    case DUAL_SURFACE:
                        mGLTarget = false;
                        mStreamTarget = false;
                        mDualStreamTarget = false;
                        break;
                    case STREAMTARGET_SURFACE:
                        mStreamTarget = true;
                        mDualStreamTarget = false;
                        mStreamTargetShadowTexture = false;
                        break;
                    case DUAL_STREAMTARGET:
                        mStreamTarget = false;
                        mDualStreamTarget = true;
                        mStreamTargetShadowTexture = false;
                        break;
                    default:
                        break;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent)
            {

            }
        });

        mUploadLogButton = (Button) findViewById(R.id.ap_bt_uploadlog);
        mUploadLogButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                uploadLog();
            }
        });

        mConectObj = new ConnectToBTPeripheral();
        mConectObj.peripheral = new BTPeripheral();

        mConectObj.peripheral.mac_addr = new byte[30];
        mConectObj.peripheral.name = "";
        updateUI();
    }


    private enum ViewItem {ISO, EV, SHUTTER, WB}

    private void setViewVisible(ViewItem viewItem) {
        mIsoSeekBar.setVisibility(View.INVISIBLE);
        mEVSeekBar.setVisibility(View.INVISIBLE);
        mShutterSeekBar.setVisibility(View.INVISIBLE);
        mWhiteBalanceSeekBar.setVisibility(View.INVISIBLE);
        mIsoValueEdit.setVisibility(View.INVISIBLE);
        mEVValueEdit.setVisibility(View.INVISIBLE);
        mShutterValueEdit.setVisibility(View.INVISIBLE);
        mWhiteBalanceValueEdit.setVisibility(View.INVISIBLE);
        if(viewItem == ViewItem.ISO) {
            mIsoSeekBar.setVisibility(View.VISIBLE);
            mIsoValueEdit.setVisibility(View.VISIBLE);
        } else if(viewItem == ViewItem.EV) {
            mEVSeekBar.setVisibility(View.VISIBLE);
            mEVValueEdit.setVisibility(View.VISIBLE);
        } else if(viewItem == ViewItem.SHUTTER) {
            mShutterSeekBar.setVisibility(View.VISIBLE);
            mShutterValueEdit.setVisibility(View.VISIBLE);
        } else if(viewItem == ViewItem.WB) {
            mWhiteBalanceSeekBar.setVisibility(View.VISIBLE);
            mWhiteBalanceValueEdit.setVisibility(View.VISIBLE);
        }
    }

    private void requestPermission() {
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
                        != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{
                            Manifest.permission.READ_EXTERNAL_STORAGE,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
                            Manifest.permission.RECORD_AUDIO,
                    },
                    MY_PERMISSIONS_REQUEST_ACCESS_EXTERNAL_STORAGE);
        }
    }

    private void saveUI() {
        SharedPreferences settings = getSharedPreferences("demo_ui", 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString("liveUrl", mLiveUrlEdit.getText().toString());
        editor.putString("liveFps", mLiveFpsEdit.getText().toString());
        editor.putString("liveBitrate", mLiveBitrateEdit.getText().toString());
        editor.putString("liveWidth", mLiveWidthEdit.getText().toString());
        editor.putString("liveHeight", mLiveHeightEdit.getText().toString());
        editor.putInt("formatSpinnerPosition", mSpinner.getSelectedItemPosition());
        editor.putInt("targetPosition", mTarget.getSelectedItemPosition());
        Log.d(TAG,"save pos " + (mSpinner.getSelectedItemPosition() + (RES_2880_2880P30 - RES_3328_832P60 - 1)));
        if((mSpinner.getSelectedItemPosition() + (RES_2880_2880P30 - RES_3328_832P60 - 1)) == RES_2880_2880P30)
        {
            mDualStream = true;
        }
        else
        {
            mDualStream = false;
        }
        Log.d(TAG,"mDualStream " + mDualStream);
        editor.commit();
    }

    private void resumeUI() {
        SharedPreferences settings = getSharedPreferences("demo_ui", 0);
        mLiveUrlEdit.setText(settings.getString("liveUrl", ""));
        mLiveFpsEdit.setText(settings.getString("liveFps", ""));
        mLiveBitrateEdit.setText(settings.getString("liveBitrate", ""));
        mLiveWidthEdit.setText(settings.getString("liveWidth", ""));
        mLiveHeightEdit.setText(settings.getString("liveHeight", ""));
        int pos = settings.getInt("formatSpinnerPosition", 0);
        if(pos < mSpinner.getCount())
            mSpinner.setSelection(pos);

        pos = settings.getInt("targetPosition", 0);
        if(pos < mSpinner.getCount())
            mTarget.setSelection(pos);
    }

    @Override
    protected void onStart() {
        super.onStart();
        resumeUI();
        requestPermission();
        new File(Environment.getExternalStorageDirectory(), "one_demo").mkdir();
    }

    @Override
    protected void onPause() {
        saveUI();
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        Log.i(TAG,"onDestroy");
        super.onDestroy();
//        mCameraService.close();
        Log.i(TAG,"skip mCameraService.close");
        EventBus.getDefault().unregister(this);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode != MY_PERMISSIONS_REQUEST_ACCESS_EXTERNAL_STORAGE)
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        boolean permissionNotGrant = false;
        if(permissions.length == 0)
            permissionNotGrant = true;
        else {
            for(int i = 0; i < permissions.length; ++i) {
                if(grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    permissionNotGrant = true;
                    break;
                }
            }
        }
        if(permissionNotGrant) {
            new AlertDialog.Builder(this)
                    .setCancelable(false)
                    .setTitle(R.string.PermissionLostDialogTitle)
                    .setMessage(R.string.PermissionLostDialogMessage)
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermission();
                        }
                    })
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .show();
        }
        else {
            new File(Environment.getExternalStorageDirectory(), "one_demo").mkdir();
        }
    }

    private void setSurfaceViewSize(int videoWidth, int videoHeight) {
        int w = mSurfaceView.getWidth();
        int h = mSurfaceView.getHeight();
        if(w * videoHeight > h * videoWidth)
            w = h * videoWidth / videoHeight;
        else
            h = w * videoHeight / videoWidth;
        android.view.ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
        lp.width = w;
        lp.height = h;
        Log.d(TAG,"surface w " + w + " h " + h);
        mSurfaceView.setLayoutParams(lp);
    }

    private void setSurface2ViewSize(int videoWidth, int videoHeight) {
        int w = mSurfaceView2.getWidth();
        int h = mSurfaceView2.getHeight();
        if(w * videoHeight > h * videoWidth)
            w = h * videoWidth / videoHeight;
        else
            h = w * videoHeight / videoWidth;
        android.view.ViewGroup.LayoutParams lp = mSurfaceView2.getLayoutParams();
        lp.width = w;
        lp.height = h;
        Log.d(TAG,"surface2 w " + w + " h " + h);
        mSurfaceView.setLayoutParams(lp);
    }

    private String readCameraOffset() {
        List<String> mList = new ArrayList<>();
        mList.add(OneDriverInfo.Options.MEDIA_OFFSET);
        mList.add(OneDriverInfo.Options.ORIGIN_OFFSET);
        Options mOptions = testGetOptions(mList);
        if(mOptions != null)
        {
            String offset = mOptions.getMediaOffset();

            Log.d(TAG,"offset " + offset);

            if(offset == null)
            {
                offset = mOptions.getOriginOffset();
                Log.d(TAG,"2offset " + offset);
            }

            return offset;
        }
        else
        {
            return "";
        }

    }

    private String mRecordPath;
    private AudioSource mAudioSource;
    private boolean mIsLiveRecord = false;

    private void startRecord(boolean recordOriginVideo, boolean livePush) {
        mCameraService.setAudioSource(mAudioSource);
        if(!livePush) {
            mIsLiveRecord = false;
            if(recordOriginVideo) {
                String filename = new File(Environment.getExternalStorageDirectory(), "one_demo/insv_" +
                        new SimpleDateFormat("MM_dd_HH_mm_ss_SSS", Locale.getDefault()).format(new Date()) + ".mp4").getAbsolutePath();
                Log.i(TAG, "start record origin video: " + filename);
                mRecordPath = "Camera";
                startCaptureWithStorage();
            }
            else {
                startCaptureWithoutStorage();
            }
            mRecordButton.setText(R.string.str_record_stop);
            mLivePushButton.setEnabled(false);
        }
        else {
            mIsLiveRecord = true;
            if(mLiveFpsEdit.getText().length() <= 0 ||
                    mLiveBitrateEdit.getText().length() <= 0 ||
                    mLiveWidthEdit.getText().length() <= 0 || mLiveHeightEdit.getText().length() <= 0) {
//                Toast.makeText(this, R.string.toast_set_live_address, Toast.LENGTH_SHORT).show();
//                return;
                Log.d(TAG,"use live param 1440x720@30fps@10Mbit");
                mLiveFpsEdit.setText("30");
                mLiveBitrateEdit.setText("10");
                mLiveWidthEdit.setText("1440");
                mLiveHeightEdit.setText("720");
            }
            startLive();
            mLivePushButton.setText(R.string.stop_push);
            mRecordButton.setEnabled(false);
        }

        mRecordState = RecordState.Recording;
    }

    private byte[] getExtraMetaData() {
        ARObject arObject = ARObject.create(null);
        arObject.setOffset(readCameraOffset());

        arObject.setCameraType("Insta360 ONE");
        arObject.setCreationTime(System.currentTimeMillis());
        ExtraMetadata extraMetadata = ARObject.bundleToExtraMetadata(arObject);
        return ExtraMetadata.ADAPTER.encode(extraMetadata);
    }

    private void stopRecord() {
        Log.i(TAG, "stop recording...");

        byte[] extra = getExtraMetaData();
        Log.d(TAG,"extra len " + extra.length);
        mCameraService.stopRecord(extra);
        mRecordState = RecordState.Stopping;

        if(!mIsLiveRecord) {
            mRecordButton.setText(R.string.str_record_stopping);
            mRecordButton.setEnabled(false);
        }
        else {
            mLivePushButton.setText(R.string.str_record_stopping);
            mLivePushButton.setEnabled(false);
        }
    }

    private void resetRecord() {
        Log.i(TAG, "reset record");
        mCameraService.resetRecord(null);
        mRecordState = RecordState.Idle;

        mRecordButton.setText(R.string.str_record);
        mRecordButton.setEnabled(true);
        mLivePushButton.setText(R.string.str_live_push);
        mLivePushButton.setEnabled(true);
    }

    private void openCamera() {
        if(mOpen)
            return;
        Log.i(TAG, "open camera");
        mOpen = true;
        mCameraService.open(null);
        mOpenButton.setText(R.string.str_close);
    }

    private void openWifi()
    {
        if(mOpen)
            return;
        Log.i(TAG, "open wifi");
        mOpen = true;
        mCameraService.openWifi(null,5000);
        mOpenButton.setText(R.string.str_close);
    }

    private void closeCamera() {
        if(!mOpen)
            return;
        Log.i(TAG, "close camera");
        if(mRecordState == RecordState.Recording) {
            Log.w(TAG, "close camera, recoding, request stop recorder firstly");
            stopRecord();
        }
        mCameraService.close(null);
        mOpenButton.setText(R.string.str_open);

        mOpen = false;
        mRunnning = false;
        // after camera close, MiniCamera will make sure record stop complete(if you requested stop)
        // or canceled(if you don't stop record).
        mRecordState = RecordState.Idle;
        updateUI();
    }

    @Override
    public void onClick(View v) {
        Log.d(TAG,"v " + v  +  " mTestSdcard " +
                mTestSdcard + " mEraseSdcard " + mEraseSdcard);
        if(v == mOpenButton) {
            if(!mOpen) {
                openCamera();
            }
            else {
                closeCamera();
            }
        }
        else if(v == mRecordButton) {
            if(mOpen) {
                if(mRecordState == RecordState.Recording) {
                    stopRecord();
                } else if(mRecordState == RecordState.Idle) {
                    startRecord(true, false);
                }
            }
        }
        else if(v == mLivePushButton) {
            if(mOpen) {
                if(mRecordState == RecordState.Recording) {
                    stopRecord();
                }
                else if(mRecordState == RecordState.Idle){
                    startRecord(false, true);
                }
            }
        }
        else if(v == mPhotoButton) {
            if(mOpen) {
                testCaptureStillImage();
            }
        }
        else if(v == mScanBT) {
            scanBT(OneDriverInfo.Request.BTPeripheralType.BTPERIPHERALTYPE_REMOTE);
        }
        else if(v == mConnectBT) {
            connectBT();
        }
        else if(v == mDeleteFileList) {
            testSetWifi();
        }
        else if(v == mGetFileList) {
            testGetWifi();
        }
        else if(v == mSetFileExtra) {
//            setFileExtra();
            startTimelapse(OneDriverInfo.Request.TimelapseMode.TIMELAPSE_INTERVAL_SHOOTING);
        }
        else if(v == mGetFileExtra) {
//            getFileExtra();
            stopTimelapse();
        }
        else if(v == mTestSdcard) {
            testSDCardSpeed();
        }
        else if(v == mEraseSdcard) {
            eraseSdcard();
        }
        else if(v == mGetOption) {
            testGetOptions();
        }
        else if(v == mGetPhotoOption) {
            testGetPhotoOptions();
        }
        else if(v == mBleButton) {
            startBle();
        }
    }

    private void startBle()
    {
        startActivity(new Intent(PlaneActivity.this, AnyScanActivity.class));
    }

    public static void saveToFile(byte[] data, int offset, int size, String filePath) {
        try {
            FileOutputStream fos = new FileOutputStream(filePath);
            fos.write(data, offset, size);
            fos.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    private void setSurface() {
        if(mDualStream)
        {
            if(mSurface2 != null && mSurface != null)
            {
                int width = mCameraService.getPreviewWidth() / 2;
                int height = mCameraService.getPreviewHeight();
                Log.i(TAG, "dual set preview ui ratio: " +
                        width + "x" + height + " mStreamTarget " + mStreamTarget);
                setSurfaceViewSize(width, height);
                setSurface2ViewSize(width, height);
                if(mStreamTarget)
                {
                    OneStreamTarget target = new OneStreamTarget(new OneStreamTarget.OnStreamFrameRenderCallback()
                    {
                        @Override
                        public void onStreamShadowRender(OneStreamTarget target, OneStreamTarget.ShadowObj shadowObj)
                        {

                        }

                        @Override
                        public void onStreamSurfaceRender(OneStreamTarget target, OneStreamTarget.StreamExtra streamExtra)
                        {

                        }
                    }, mSurface, mSurface2);
                    mCameraService.setSurface(target);
                }
                else
                {
                    mCameraService.setSurface(mSurface,mSurface2);
                }
            }
        }
        else
        {
            int width = mCameraService.getPreviewWidth();
            int height = mCameraService.getPreviewHeight();
            Log.i(TAG, "single set preview ui ratio: "
                    + width + "x" + height + " mStreamTarget " + mStreamTarget);
            setSurfaceViewSize(width, height);
            if(mStreamTarget)
            {
                OneStreamTarget target = new OneStreamTarget(new OneStreamTarget.OnStreamFrameRenderCallback()
                {
                    @Override
                    public void onStreamShadowRender(OneStreamTarget target, OneStreamTarget.ShadowObj shadowObj)
                    {

                    }

                    @Override
                    public void onStreamSurfaceRender(OneStreamTarget target, OneStreamTarget.StreamExtra streamExtra)
                    {

                    }
                },mSurface);
                mCameraService.setSurface(target);
            }
            else
                mCameraService.setSurface(mSurface);
        }

//        if(mDualStream)
//        {
//            if(mSurface2 != null && mSurface != null)
//            {
//
//            }
//        }
//        else
//        {
//
//        }
    }

    public static boolean isOffsetValid(String offset) {
        if(offset == null)
            return false;
        if(offset.length() < 40)
            return false;
        String pattern = "[\\d_\\.\\-\\+\\s\\n\\t]+";

        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(offset);
        if(!m.find())
            return false;
        if(m.start() != 0 || m.end() != offset.length())
            return false;
        return true;
    }

    private void setVersionInfo() {
//        mVersionTextView.setText("App: " + getAppVersion() + "\n" + getFwVersionInfo());
    }

    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
    private static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    public void testGetPhotoOptions()
    {
//        long start = System.nanoTime();
//        PhotoOptions mOptions = mCameraService.getPhotoOptions(OneDriverInfo.PhotoOptionsConstants.FunctionMode.FUNCMODE_NORMAL);
//
//        long end = System.nanoTime();
//
//        Log.d(TAG,"testGetPhotoOptions cost " + (end - start)/1000000);

        mCameraService.getPhotoOptionsAsync(OneDriverInfo.PhotoOptionsConstants.FunctionMode.FUNCMODE_NORMAL);
        Log.d(TAG,"add getOptionsAsync");
    }

    private Options testGetAllOptions()
    {
        return (Options)startWait(mCameraService.getAllOptionsAsync(),OneDriverInfo.Response.InfoType.GET_OPTIONS);
    }

    public void testGetOptions()
    {
        long start = System.nanoTime();
        Options mOptions = testGetAllOptions();

        if(mOptions != null)
        {
            long end = System.nanoTime();
            Log.d(TAG,"testGetAllOptions cost " + (end - start)/1000000 +
                    " getFree " +
                    mOptions.getStorageFreeSpace());
        }

        OneLatestIDR mLatestIDRFrame = mCameraService.getLatestIDRFrame();
        Log.d(TAG,"getLatestIDR");

        if(mLatestIDRFrame!= null && mLatestIDRFrame.mOneGyroField != null)
            android.util.Log.d(TAG,"found idr mLatestIDRFrame.mOneGyroField ts "
                    + mLatestIDRFrame.mOneGyroField.timestampNs + " offset " + mLatestIDRFrame.mIDRFrame.offset
                    + " size " + mLatestIDRFrame.mIDRFrame.size);
    }

    private PhotoOptions testPhotoOptions()
    {
        return (PhotoOptions)startWait(mCameraService.getPhotoOptionsAsync(funcMode),OneDriverInfo.Response.InfoType.GET_PHOTOGRAPHY_OPTIONS);
    }

    public void getPhotoOption()
    {
        Log.d(TAG,"getPhotoOptions");
        PhotoOptions mPhotoOptions = testPhotoOptions();

        if(mPhotoOptions != null)
        {
            int brightness = mPhotoOptions.getBrightness();
            Log.d(TAG,"getPhotoOptions brightness " + brightness);
            int [] aeManuls = mPhotoOptions.getAEManualMeterWeight();
            if(aeManuls != null)
            {
                Log.d(TAG,"getPhotoOptions aeManuls " + aeManuls.length);

                for(int i = 0; i < aeManuls.length;i++)
                {
                    Log.d(TAG," " + aeManuls[i]);
                }
                Log.d(TAG,"getPhotoOptions aeManuls over " + aeManuls.length);
            }
            else
            {
                Log.d(TAG,"aeManuls null");
            }
        }
    }

    public void testSetPhotoOption()
    {
        PhotoOptions mPhotoOptions = new PhotoOptions();
        int [] aeVal = new int[4];

        aeVal[0] = 0;
        aeVal[1] = 1;
        aeVal[2] = 2;
        aeVal[3] = 3;
        Log.d(TAG,"setBrightness");
        mPhotoOptions.setBrightness(10);
        Log.d(TAG,"setAEManualMeterWeight");
        mPhotoOptions.setAEManualMeterWeight(aeVal);
        Log.d(TAG,"testSetPhotoOption 2");
        mCameraService.setPhotoOptionsAsync(OneDriverInfo.PhotoOptionsConstants.FunctionMode.FUNCMODE_NORMAL,mPhotoOptions);
    }

    private void testTimelapse()
    {
        Log.d(TAG,"testTimelapse");
        GetTimelapseOptions mGet = new GetTimelapseOptions();
        mCameraService.getTimelapseOptionsAsync(mGet);

//        Log.d(TAG,"durationS " + mInfo.durationS);
//        Log.d(TAG,"lapseTimeMs " + mInfo.lapseTimeMs);

        SetTimelapseOptions mSet = new SetTimelapseOptions();

        mSet.timelapse_options = new TimelapseOptionsInfo();
//        mSet.timelapse_options.durationS = mInfo.durationS;
//        mSet.timelapse_options.lapseTimeMs = mInfo.lapseTimeMs;
        Log.d(TAG,"setTimelapse");
        mCameraService.setTimelapseOptionsAsync(mSet);
        Log.d(TAG,"testTimelapse suc");
    }

    public void testSetOption()
    {
        Log.d(TAG,"1set Options");

        Options mOptions = new Options();
//
        mOptions.setLongPressint(OneDriverInfo.Options.ButtonPressMode.CAPTURE);
        mOptions.setTripleint(OneDriverInfo.Options.ButtonPressMode.TAKE_PICTURE);
        mOptions.setClickint(OneDriverInfo.Options.ButtonPressMode.ACTION_TIMELAPSE_VIDEO);

        mOptions.setVideoResolution(30,1920,960);
        mOptions.setPhotoSize(4000,3000);
        mOptions.setOriginOffset("3700");
        long start = System.nanoTime();
        mCameraService.setOptionsAsync(mOptions);
        Log.d(TAG,"set Options suc");
        long end = System.nanoTime();

        Log.d(TAG,"testGetPhotoOptions cost " + (end - start)/1000000);
//    mOptions.setVideoBitrate();
//
//
//    mOptions.setAudioBitrate();
//
//    mOptions.setAudioSampleRate();
//
//    mOptions.setOriginOffset();
//
//
//    mOptions.setCaptureLimitTime();
//
//
//    mOptions.setGPSTimeout();
//
//    mOptions.setLocalTime();
//
//
//    mOptions.setTimezoneSecodeFromGMT();
//
//    mOptions.setMute();
//
//    mOptions.setButtonPressOption(ButtonPressOptions obj)
//
//    mOptions.setClickint();
//
//    mOptions.setDoubleint();
//
//    mOptions.setTripleint();
//    mOptions.setLongPressint();
//    mOptions.setActiveTime();
//    mOptions.setMediaOffset();
//    mOptions.setSelfTimer();
//    mOptions.setGyroSampleRate();
//    mOptions.setAccFullRange();
//    mOptions.setGyroFullRange();
//    mOptions.setTakeRawPicture();
//    mOptions.setLogMode();
    }

    private void testAll()
    {
//        testCaptureStillImage();
//        testCaptureStillImageWithouStorage();
//
//        startCaptureWithStorage(captureMode);
//        stopRecord();
//        cancelCaptureWithStorage();
//        calibrateGyro();
//
////        getRecordStatus();
//        startTimeplapse();
//        stopTimeplapse();
//        setFileExtra();
//        getFileExtra();
//
        getFileInfoList();
//        getGyro();
//        getMiniThumbnail();
//
//        testSDCardSpeed();
        Log.d(TAG,"testAll");
        testGetWifi();
        testSetWifi();
        testGetWifi();
//
//        openCameraWifi();
//
//        closeCameraWifi();
    }

    private void startTimelapse(int mode)
    {
        StartTimelapse obj = new StartTimelapse();
        obj.mode = mode;

        mTimelapseMode = mode;
        mCameraService.startTimeplapse(obj);
    }

    private void stopTimelapse()
    {
        StopTimelapse obj = new StopTimelapse();
        obj.mode = mTimelapseMode;
        mCameraService.stopTimeplapse(obj);
    }

    private void testGetWifi()
    {
        List<String> mList = new ArrayList<>();
        mList.add(OneDriverInfo.Options.WIFI_CH);
        mList.add(OneDriverInfo.Options.WIFI_SSID);

        mList.add(OneDriverInfo.Options.WIFI_PWD);
        mList.add(OneDriverInfo.Options.WIFI_MODE);

        Options mOptions = testGetOptions(mList);
        if(mOptions != null)
        {
            com.arashivision.onecamera.camerarequest.WifiInfo info = mOptions.getWifiInfo();
            Log.d(TAG,"wifi info " + info);
            Log.d(TAG,"wifi ch " + info.getChannel());
        }

        scanBT(OneDriverInfo.Request.BTPeripheralType.BTPERIPHERALTYPE_ALL);
        connectBT();
        getFileInfoList();
    }

    private void testSetWifi()
    {
        Options mOptions = new Options();

        WifiInfo info = new WifiInfo();
        String ssid = "One2_1234567";
        /**
         * 36 as 5G
         * 0 as 2.4G
         */
        info.setChannel(36);
        info.setSsid(ssid);
        info.setPwd("1234567890");
        info.setMode(OneDriverInfo.Options.WIFI_MODE_TYPE.AP);
        mOptions.setWifiInfo(info);

        Log.i(TAG,"set ssid " + ssid);
        mCameraService.setOptionsAsync(mOptions);
    }

    private void openCameraWifi()
    {
        long id = mCameraService.openCameraWifi();
        Log.d(TAG,"openCameraWifi id " + id);
    }

    private void closeCameraWifi()
    {
        long id = mCameraService.closeCameraWifi();
        Log.d(TAG,"closeCameraWifi id " + id);
    }

    private void testSDCardSpeed()
    {
        TestSDCardSpeed obj = new TestSDCardSpeed();
        obj.block_size = 4096;
        obj.duration = 60;
        obj.times = 3;

        mCameraService.testSDCardSpeed(obj);
    }

    private void eraseSdcard()
    {
        long eraseId = mCameraService.eraseSDCard();
        Log.d(TAG,"erase id " + eraseId);
    }

    private void testCaptureStillImage()
    {
        Log.i(TAG, "testCaptureStillImage");
        TakePicture obj = new TakePicture();
        obj.mode = OneDriverInfo.Request.ImageMode.NORMAL;
        obj.extra_metadata = null;
        obj.aeb_ev_bias = new int[3];
        obj.aeb_ev_bias[0] = 0;
        obj.aeb_ev_bias[1] = 1;
        obj.aeb_ev_bias[2] = 2;
        mCameraService.captureStillImage(obj);
    }

    private void testCaptureStillImageWithouStorage(String mPath,boolean bStitch)
    {
        Log.i(TAG, "testCaptureStillImageWithouStorage");
        TakePicture obj = new TakePicture();
        obj.mode = OneDriverInfo.Request.ImageMode.NORMAL;
        obj.extra_metadata = null;
        obj.aeb_ev_bias = new int[3];
        obj.aeb_ev_bias[0] = 0;
        obj.aeb_ev_bias[1] = 1;
        obj.aeb_ev_bias[2] = 2;
        mCameraService.captureStillImageWithouStorage(mPath,bStitch,obj);
    }

    private void startCaptureWithoutStorage()
    {
        Log.d(TAG,"startCaptureWithoutStorage");
        stopStreaming();
//        mCameraService.setAudioParam(true,48000,128000,OneDriverInfo.AudioCodec.ADTS);
        startStreaming(true);

        StartCaptureWithoutStorage obj = new StartCaptureWithoutStorage();
        String filename = new File(Environment.getExternalStorageDirectory(), "one_demo/VID" +
                new SimpleDateFormat("MM_dd_HH_mm_ss_SSS", Locale.getDefault()).format(new Date()) + ".insv").getAbsolutePath();
        obj.path = filename;
        obj.format = OneDriverInfo.RecordFormat.VIDEO_FORMAT_MP4;
        obj.width = mVideoWidth;
        obj.height = mVideoHeight;
        obj.fps = 30;
        obj.bitrate = 20000000;
        obj.mRecordType = RecordType.Origin;
        obj.renderMode = RenderMode.withGlRenderer(RenderMethod.DualFishEyeStitchingPlanar);
        mRecordPath = filename;
        mCameraService.startRecordWithoutStorage(obj);
    }

    private void startLive()
    {
        if(!mPanoMode)
        {
            switchDualFishMode();
        }
        StartCaptureWithoutStorage obj = new StartCaptureWithoutStorage();

        String url;
        if(mLiveUrlEdit.getText().length() > 0) {
            url = mLiveUrlEdit.getText().toString();
        }
        else {
//            url = "rtmp://send1.douyu.com/live/645917rYqxJXyrna?wsSecret=751fd5fcb19377375dc2ab3dc26a9600&wsTime=5a169941&wsSeek=off";
//            url = new File(Environment.getExternalStorageDirectory(), "one_demo/video_" +
//                    new SimpleDateFormat("MM_dd_HH_mm_ss_SSS", Locale.getDefault()).format(new Date()) + ".flv").getAbsolutePath();
//            Toast.makeText(this, R.string.live_addr_empty_toask, Toast.LENGTH_LONG).show();
            url = "rtmp://video-center.alivecdn.com/livecdn/test526?vhost=hls.insta360.com";
        }

        double fps = Double.valueOf(mLiveFpsEdit.getText().toString());
        double bitrateMbps = Double.valueOf(mLiveBitrateEdit.getText().toString());
        int width = Integer.valueOf(mLiveWidthEdit.getText().toString());
        int height = Integer.valueOf(mLiveHeightEdit.getText().toString());

        obj.path = url;
        obj.format = OneDriverInfo.RecordFormat.VIDEO_FORMAT_FLV;
        obj.width = width;
        obj.height = height;
        obj.bitrate = (int)(bitrateMbps * 1024 * 1024);
        obj.fps = (int)fps;
        obj.renderMode = RenderMode.withGlRenderer(RenderMethod.DualFishEyeStitchingPlanar);
        obj.mRecordType = RecordType.ReEncoded;
        Log.i(TAG, "fps" + fps);
        Log.i(TAG, "bitrateMbps" + bitrateMbps);
        Log.i(TAG, "width" + width);
        Log.i(TAG, "height" + height);
        Log.i(TAG, "obj.path " + obj.path);

        stopStreaming();
        mCameraService.setAudioParam(true,48000,128000,OneDriverInfo.AudioCodec.ADTS);
        startStreaming(true);

        mCameraService.startRecordWithoutStorage(obj);
    }

    private void stopStreaming()
    {
        mCameraService.stopStreaming(null);
    }

    private boolean isOne2()
    {
        return mGyroType.equals(GyroType.One2);
    }

    private void startStreaming(boolean audioEnable)
    {
        if(isOne2())
        {
            Log.d(TAG,"mVideoWidth " + mVideoWidth +
                    " mVideoHeight " + mVideoHeight
                    + " fps " + fps +
                    " bitrate " + bitRate + " gyro "
                    + bEnableGyro + " mPreviewNum " + mPreviewNum + " audioEnable " + audioEnable);
            Log.d(TAG,"mDualStream " + mDualStream);

            StartStreamingParam param = new StartStreamingParam();

            VideoParam firstParam = new VideoParam();
            firstParam.width = mVideoWidth;
            firstParam.height = mVideoHeight;
            firstParam.fps = fps;
            firstParam.enableGyro = bEnableGyro;
            firstParam.bitrate = bitRate;
            param.setFirstVideoParam(firstParam);

            VideoParam secParam = new VideoParam();

            secParam.width = 960;
            secParam.height = 480;
            secParam.fps = 30;
            secParam.enableGyro = bEnableGyro;
            secParam.bitrate = 3;

            param.setSecVideoParam(secParam);

            AudioParam audioParam = new AudioParam();

            audioParam.enable = audioEnable;
            if(audioEnable)
            {
                audioParam.bitrate = 128000;
                audioParam.codec = OneDriverInfo.AudioCodec.ADTS;
                audioParam.sampleRate = 48000;
            }

            param.setAudioParam(audioParam);

            param.setPreviewNum(mPreviewNum);
            param.setGyroType(mGyroType);
            param.setDualStream(mDualStream);

            mCameraService.startStreaming(param);
        }
        else
        {
            mCameraService.startStreaming();
        }
    }

    private void startCaptureWithStorage()
    {
        if(!isOne2())
        {
            stopStreaming();
            mCameraService.setAudioParam(true,48000,128000,OneDriverInfo.AudioCodec.RAW);
            startStreaming(true);
        }

        mCameraService.startRecord();
    }

    private void scanBT(int type)
    {
        ScanBTPeripheral obj = new ScanBTPeripheral();
        Log.d(TAG,"scanBT type " + obj.peripheral_type);
        obj.peripheral_type = type;
        long ret = mCameraService.scanBleDevice(obj);
        Log.d(TAG,"scanBT " + ret);
    }

    private void connectBT()
    {
        Log.d(TAG,"mConectObj mac " +
                mConectObj.peripheral.mac_addr.length +
                " name " + mConectObj.peripheral.name);
        long ret = mCameraService.connectBleDevice(mConectObj);
        Log.d(TAG,"ret " + ret);
    }

    private void getTunelPort()
    {
        int port = mCameraService.getTunelPort();

        Log.d(TAG,"get tunel port " + port);
    }

    private void setFileExtra()
    {
        SetFileExtra obj = new SetFileExtra();
        obj.uri = "sdcard1";
        obj.extra_type = 3;
        mCameraService.setFileExtra(obj);
    }

    private void getFileExtra()
    {
        GetFileExtra obj = new GetFileExtra();
        obj.uri = "/DCIM/Camera01";
        obj.extra_type = 2;
        obj.mGyroOptionIndexRange = new GyroOptionIndexRange();
        obj.mGyroOptionIndexRange.start = 0;
        obj.mGyroOptionIndexRange.count = 10;

        obj.mGyroOptionTimeRange = new GyroOptionTimeRange();
        obj.mGyroOptionTimeRange.start = 0;
        obj.mGyroOptionTimeRange.duration = 10;
        mCameraService.getFileExtra(obj);
    }

    private void getFileList()
    {
        GetFileList obj = new GetFileList();

        obj.media_type = OneDriverInfo.Request.MediaType.MEDIATYPE_VIDEO_AND_PHOTO;
        obj.start = 0;
        obj.limit = 10;
        mCameraService.getFileList(obj);
    }

    private void getFileInfoList()
    {
        mCameraService.getFileInfoList();
    }

    private void deleteFileList()
    {
        DeleteFiles obj = new DeleteFiles();

        obj.mDeleteUris = new ArrayList<>();

        obj.mDeleteUris.add("/DCIM/Camera01/VID_19731017_140346_005.insv");

        mCameraService.deleteFileList(obj);
    }

    private void getGyro()
    {
//        GetGyro obj = new GetGyro();
//        obj.count = 100;
//        GetGyroResp mResp = mCameraService.getGyro(obj);
//        if(mResp != null && mResp.mGyroDataList != null)
//        {
//            Log.d(TAG,"mResp.mGyroDataList size " + mResp.mGyroDataList.size());
//            for(int i = 0; i <mResp.mGyroDataList.size();i++ )
//            {
//                GyroData mData = mResp.mGyroDataList.get(i);
//                Log.d(TAG,"ts " + mData.timestamp + " " + mData.accelX + " " +
//                        mData.accelY + " " + mData.accelZ
//                        + " " + mData.rotationX + " " +
//                        mData.rotationY + " " + mData.rotationZ);
//            }
//        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onOpenEvent(CameraService.OpenEvent event) {
        Log.i(TAG, "camera has open");
        mRunnning = true;

        if(mFwReleaseName != null)
            Log.i(TAG, "firmware release name: " + mFwReleaseName);
        mAudioSource = AudioSource.AUDIO_CAMERA;

        if(mFwReleaseName != null && mFwReleaseName.equals("Air2Assume")) {
            Toast.makeText(this, "Air2 开发: 未设置拍照参数，拍照不可用!", Toast.LENGTH_SHORT).show();
        }

//        if(bEnableGyro)
//            mCameraService.suggestApplyGyroStabilizer(true,false);

        Options mOptions = testGetAllOptions();
        if(mOptions != null)
        {
            Log.d(TAG,"gyro range " + mOptions.getGyroSampleRate() +
                    " accel range " + mOptions.getAccFullRange());
            mOffset = mOptions.getMediaOffset();


            Log.d(TAG,"getMediaOffset " + mOffset);

            Log.d(TAG,"getOriginOffset " + mOptions.getOriginOffset());
        }

        mCameraService.syncCaptureStatus();

        getTunelPort();
//        if(mBitrateValueEdit.getText().length() > 0)
//        {
//            Log.d(TAG,"mLiveBitrateEdit.getText().toString() " + mBitrateValueEdit.getText().toString());
//            double bitrateMbps = Double.valueOf(mBitrateValueEdit.getText().toString());
//            bitRate = (int)bitrateMbps;
//            Log.d(TAG,"2 bitRate " + bitRate);
//        }

        if(mExposeModeSwitch.isChecked())
        {
            bEnableGyro = true;
        }
        else
        {
            bEnableGyro = false;
        }

        if(mStreamNum.isChecked())
        {
            mPreviewNum = 1;
        }
        else
        {
            mPreviewNum = 0;
        }
        mCameraService.setVideoParam(mVideoWidth,mVideoHeight,fps, bitRate,bEnableGyro);

//        String offset = "2_762.040_797.100_746.480_0.000_0.000_90.000_762.020_2228.920_788.560_0.000_-0.800_90.400_3008_1504_1035";
//        mCameraService.updatePanoOffset(offset);
        //        mCameraService.updatePanoOffset(mOptions.getMediaOffset());



        startStreaming(false);

        if(mCameraService != null && mSurface != null && mSurface2 != null) {
            setSurface();
        }

        updateUI();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDetachEvent(CameraService.DetachEvent event) {
        Log.i(TAG, "camera has detached");
        showCameraDetach();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onErrorEvent(CameraService.ErrorEvent event) {
        Log.i(TAG, "camera met error: " + event.error);
        showCameraError(event.error);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRecordCompleteEvent(CameraService.RecordCompleteEvent event) {
        Log.i(TAG, "record complete");
        if(event.recordType == RecordType.Origin) {
        }

        mRecordState = RecordState.Idle;
        mRecordButton.setText(R.string.str_record);
        mLivePushButton.setText(R.string.str_live_push);
        if(mRunnning) {
            mRecordButton.setEnabled(true);
            mLivePushButton.setEnabled(true);
        }
        Toast.makeText(PlaneActivity.this, getResources().getString(R.string.str_msg_record_complete),
                Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRecordCompleteWithStorageEvent(CameraService.RecordCompleteWithStorageEvent event) {
        Log.i(TAG, "onRecordCompleteWithStorageEvent state " + event.state);

        Log.i(TAG,"error_code. " + event.mResult.error_code);
        Log.i(TAG,"uri. " + event.mResult.video.uri);
        Log.i(TAG,"file_size. " + event.mResult.video.file_size);
        Log.i(TAG,"total_time. " + event.mResult.video.total_time);
        if(event.state == OneDriverInfo.Response.OpState.FAILED)
        {
            showRecordError(0);
        }
        else if(event.state != OneDriverInfo.Response.OpState.STARTED)
        {
            mRecordState = RecordState.Idle;
            mRecordButton.setText(R.string.str_record);
            mLivePushButton.setText(R.string.str_live_push);
            if(mRunnning) {
                mRecordButton.setEnabled(true);
                mLivePushButton.setEnabled(true);
            }
            Toast.makeText(PlaneActivity.this, getResources().getString(R.string.str_msg_record_complete),
                    Toast.LENGTH_LONG).show();
        }

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRecordErrorEvent(CameraService.RecordErrorEvent event) {
        Log.i(TAG, "record error " + event.error);
        if(mRecordState == RecordState.Idle)
            return;
        showRecordError(event.error);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onPhotoCapturedEvent(CameraService.PhotoCapturedEvent event) {
        Log.i(TAG, "capture photo result: " + event.error);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onStillImageCapturedEvent(CameraService.StillImageCapturedEvent event) {
        mPhotoView.setImageBitmap(BitmapFactory.decodeFile(event.path));
        Toast.makeText(PlaneActivity.this, getResources().getString(R.string.str_msg_takephoto_complete),
                Toast.LENGTH_LONG).show();

        //if(!mPanoMode) {
        //    try {
        //        ExtraDataOperator.getInstace().getData(event.path).getInfo().setOffset(mCameraService.readCameraPanoOffset());
        //        ExtraDataOperator.getInstace().save(event.path);
        //    } catch(IOException e) {
        //        e.printStackTrace();
        //    }
        //}
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRecordFpsUpdateEvent(CameraService.RecordFpsUpdateEvent event) {
//        Log.i(TAG, "fps update: " + event.fps);
        if(mIsLiveRecord && mRecordState == RecordState.Recording)
            mLiveFpsTextView.setText("FPS: " + event.fps);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onLivePushStartedEvent(CameraService.LivePushStartedEvent event) {
        Log.i(TAG, "live push started event: " + event.url);
        if(mIsLiveRecord && mRecordState == RecordState.Recording) {
            Toast.makeText(this, R.string.live_push_start_ok, Toast.LENGTH_SHORT).show();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onUsbTestSpeedEvent(CameraService.UsbTestSpeedEvent event) {
        Log.i(TAG, "UsbTestSpeedEvent event: " + event.speed);
        String text = "speed " +  event.speed;
        mLiveBitrateEdit.setText(text);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onBleDisconnectEvent(CameraService.BleDisconnectEvent event) {
        Log.i(TAG, "onBleDisconnectEvent event: " + event.mBTPeripheral.mac_addr + " name　" +
                event.mBTPeripheral.name );
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onBleDiscoverEvent(CameraService.BleDiscoverEvent event) {
        Log.i(TAG, "onBleDiscoverEvent event: " + event.mBTPeripheral.mac_addr.length + " name　" +
                event.mBTPeripheral.name );
        mConectObj.peripheral.mac_addr = event.mBTPeripheral.mac_addr;
        mConectObj.peripheral.name = event.mBTPeripheral.name;
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onBleConnectEvent(CameraService.BleConnectEvent event) {
        Log.i(TAG, "onBleConnectEvent event: " + event.mBTPeripheral.mac_addr + " name　" +
                event.mBTPeripheral.name );
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onUSBErrorEvent(CameraService.USBErrorEvent event) {
        Log.d(TAG,"state " + event.state + " error " + event.error);
        if(event.state == OneDriverInfo.Notification.UsbState.ERROR)
        {
                closeCamera();
        }
    }

    private void updateUI() {
        if(!mRunnning) {
            mScanBT.setEnabled(false);
            mConnectBT.setEnabled(false);
            mDeleteFileList.setEnabled(false);
            mGetFileList.setEnabled(false);
            mSetFileExtra.setEnabled(false);
            mGetFileExtra.setEnabled(false);

            mPhotoButton.setEnabled(false);
            mRecordButton.setEnabled(false);
            mLivePushButton.setEnabled(false);
            mSurfaceView.setEnabled(false);
            if(mSurfaceView2 != null)
            {
                mSurfaceView2.setEnabled(false);
            }

            mGetInfoButton.setEnabled(false);
            mIsoSeekBar.setEnabled(false);
            mEVSeekBar.setEnabled(false);
            mShutterSeekBar.setEnabled(false);
            mWhiteBalanceSeekBar.setEnabled(false);
            mEraseSdcard.setEnabled(false);
            mTestSdcard.setEnabled(false);
            mGetOption.setEnabled(false);
            mGetPhotoOption.setEnabled(false);
        } else {
            mScanBT.setEnabled(true);
            mConnectBT.setEnabled(true);
            mDeleteFileList.setEnabled(true);
            mGetFileList.setEnabled(true);
            mSetFileExtra.setEnabled(true);
            mGetFileExtra.setEnabled(true);

            mPhotoButton.setEnabled(true);
            mRecordButton.setEnabled(true);
            mLivePushButton.setEnabled(true);
            mSurfaceView.setEnabled(true);
            if(mSurfaceView2 != null)
                mSurfaceView2.setEnabled(true);
            mGetInfoButton.setEnabled(true);
            mIsoSeekBar.setEnabled(true);
            mEVSeekBar.setEnabled(true);
            mShutterSeekBar.setEnabled(true);
            mWhiteBalanceSeekBar.setEnabled(true);
            mEraseSdcard.setEnabled(true);
            mTestSdcard.setEnabled(true);
            mGetOption.setEnabled(true);
            mGetPhotoOption.setEnabled(true);
        }
    }

    private void showCameraError(int err) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle("相机错误");
        if(err == Error.ERR_NOCAMERA) {
            builder.setMessage("相机未接入");
        } else if(err == Error.ERR_PERMISSION) {
            builder.setMessage("未授权应用访问相机");
        } else if(err == Error.ERR_OPENDEVICE) {
            builder.setMessage("无法打开相机， 其他应用正在使用相机？");
        } else if(err == Error.ERR_INITCAMERA) {
            builder.setMessage("无法初始化相机， 请插拔相机重试");
        } else if(err == Error.ERR_PLAYER) {
            builder.setMessage("预览流无法播放");
        } else if(err == Error.ERR_IO) {
            builder.setMessage("未知错误");
        } else if(err == Error.ERR_CAMERA_STREAM_READ_ERROR) {
            builder.setMessage("无法读取预览流");
        } else if(err == Error.ERR_CAMERA_STREAM_READ_TIMEOUT) {
            builder.setMessage("预览流超时");
        } else {
            builder.setMessage("未知错误: " + err);
        }
        builder.setCancelable(false).setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                closeCamera();
            }
        });
        builder.setIcon(android.R.drawable.ic_dialog_alert);
        builder.create().show();
    }

    public void showCameraDetach() {
        new AlertDialog.Builder(this).
                setTitle("注意").
                setMessage("相机已断开").
                setCancelable(false).
                setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Log.d(TAG,"close Camera");
                        closeCamera();
                        Log.d(TAG,"2close Camera");
                    }
                }).
                setIcon(android.R.drawable.ic_dialog_alert).create().show();
    }

    private void showRecordError(int err) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle("错误");
        builder.setMessage("录制过程中出错");
        builder.setCancelable(false);
        builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                resetRecord();
            }
        });
        builder.setIcon(android.R.drawable.ic_dialog_alert);
        builder.create().show();
    }

    private void uploadLog() {
        Toast.makeText(PlaneActivity.this,"start collect and upload log",Toast.LENGTH_LONG).
                show();
//        LogUploader.postLog(new LogUploader.LogTask(PlaneActivity.this,"http://lezera.com:8000/",
//                1024*1024));
    }
}

